package com.cq.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.cq.excelModel.*;
import com.cq.mapper.ActivityAnalysisMapper;
import com.cq.pojo.*;
import com.cq.pojo.dto.MediaSlotPageDTO;
import com.cq.result.PageResult;
import com.cq.service.ActivityService;
import com.cq.service.AlogService;
import com.cq.utils.AlogUtil;
import com.cq.utils.ExcelUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActivityServiceImpl implements ActivityService {

    @Autowired
    private ActivityAnalysisMapper activityAnalysisMapper;
    @Autowired
    private AlogService alogService;

    @Override
    public List<ActivityAnalysis> findNewActivities() {
        return activityAnalysisMapper.findNewActivities();
    }

    @Override
    public ActivityAnalysis getAlog(String campaignId) {
        // 查询数据库中信息
        ActivityAnalysis activityAnalysis = activityAnalysisMapper.selectAnByCId(campaignId);
        // 查询公式计算信息
        Alog alog = alogService.getAlog(campaignId);
        activityAnalysis.setAlog(alog);

        AlogAvg alogAvg = alogService.getAlogAvg(activityAnalysis.getActivityType());

        AlogDiff diff = AlogUtil.getAlogDiff(alog, alogAvg);
        activityAnalysis.setAlogDiff(diff);

        return activityAnalysis;
    }

    @Override
    public void download(HttpServletResponse response) throws IOException {
        // 1.获取数据
        List<ActivityAnalysis> list = activityAnalysisMapper.selectByExample(null);

        // 2.设置文件名
        String fileName = System.currentTimeMillis() + "";

        List<ActivityAnalysisExcel> collect = list.stream()
                .map((ac) -> {
                    ActivityAnalysisExcel excel = new ActivityAnalysisExcel();
                    BeanUtils.copyProperties(ac, excel);
                    return excel;
                }).collect(Collectors.toList());
        // 3.设置格式，生成文档
        HorizontalCellStyleStrategy strategy = ExcelUtil.getHorizontalCellStyleStrategy(response, fileName);
        EasyExcel.write(response.getOutputStream(), ActivityAnalysisExcel.class)
                .registerWriteHandler(strategy)
                .sheet("归因概览")
                .doWrite(collect);
    }

    @Override
    public ConversionIncome getConversionIncome(String campaignId, String status) {
        List<ConversionIncome> list = activityAnalysisMapper.getConversionIncome(campaignId);
        ConversionIncome con = new ConversionIncome();
        if (list != null && list.size() != 0) {
            con = list.get(0);
        }
        BigDecimal emacRate = new BigDecimal("0");
        BigDecimal etnccRate = new BigDecimal("0");
        if (status.equals("1")) {
            emacRate = new BigDecimal(con.getMonthlyActiveMemberCount()).divide(new BigDecimal(con.getExposureCount()),2, RoundingMode.HALF_UP);
            etnccRate = new BigDecimal(con.getNewMemberAcquisitionCount()).divide(new BigDecimal(con.getExposureCount()),2, RoundingMode.HALF_UP);

            // 均值
            ConversionIncome incomeAvg = activityAnalysisMapper.getConversionIncomeAvg();
            con.setEmacRateAvg(incomeAvg.getEmacRateAvg());
            con.setEtnccRateAvg(incomeAvg.getEtnccRateAvg());

            // 差值
            con.setEmacRateDiff(emacRate.subtract(incomeAvg.getEmacRateAvg()));
            con.setEtnccRateDiff(etnccRate.subtract(incomeAvg.getEtnccRateAvg()));
        }else {
            emacRate = new BigDecimal(con.getMonthlyActiveMemberCount()).divide(new BigDecimal(con.getExposureUserCount()),2, RoundingMode.HALF_UP);
            etnccRate = new BigDecimal(con.getNewMemberAcquisitionCount()).divide(new BigDecimal(con.getExposureUserCount()),2, RoundingMode.HALF_UP);

            // 均值
            ConversionIncome avgUser = activityAnalysisMapper.getConversionIncomeAvgUser();
            con.setEmacRateAvg(avgUser.getEmacRateAvg());
            con.setEtnccRateAvg(avgUser.getEtnccRateAvg());

            // 差值
            con.setEmacRateDiff(emacRate.subtract(avgUser.getEmacRateAvg()));
            con.setEtnccRateDiff(etnccRate.subtract(avgUser.getEtnccRateAvg()));
        }

        con.setEmacRate(emacRate);
        con.setEtnccRate(etnccRate);

        return con;
    }

    @Override
    public void conversionIncomeDownload(HttpServletResponse response, String campaignId, String status) throws IOException {
        ConversionIncome con = this.getConversionIncome(campaignId, status);
        ConversionIncomeExcel excel = new ConversionIncomeExcel();
        BeanUtils.copyProperties(con, excel);

        List<ConversionIncomeExcel> list = new ArrayList<>();
        list.add(excel);
        String fileName = System.currentTimeMillis() + "";

        EasyExcel.write(response.getOutputStream(), ConversionIncomeExcel.class)
                .registerWriteHandler(ExcelUtil.getHorizontalCellStyleStrategy(response, fileName))
                .sheet("转化效益分析")
                .doWrite(list);
    }

    @Override
    public PageResult findMediaSlot(MediaSlotPageDTO dto) {
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());

        List<MediaSlot> mediaSlotList = getMediaSlotList(dto);

        PageInfo<MediaSlot> info = new PageInfo<>(mediaSlotList);

        return new PageResult<MediaSlot>(info.getPageNum(), info.getPageSize(), info.getTotal(), info.getList());
    }

    private List<MediaSlot> getMediaSlotList(MediaSlotPageDTO dto) {
         return activityAnalysisMapper.selectMediaSlot(dto.getCampaignId(), dto.getContactPoint(), dto.getOrderField(), dto.getOrderBy(), dto.getMedia());
    }

    @Override
    public void mediaSlotDownload(HttpServletResponse response, MediaSlotPageDTO dto) throws IOException {
        List<MediaSlot> mediaSlot = this.getMediaSlotList(dto);

        String fileName = System.currentTimeMillis() + "";

        List<MediaSlotExcel> list = mediaSlot.stream()
                .map(m -> {
                    MediaSlotExcel excel = new MediaSlotExcel();
                    BeanUtils.copyProperties(m, excel);
                    return excel;
                }).collect(Collectors.toList());

        EasyExcel.write(response.getOutputStream(), MediaSlotExcel.class)
                .registerWriteHandler(ExcelUtil.getHorizontalCellStyleStrategy(response, fileName))
                .sheet("媒介归因排名")
                .doWrite(list);
    }

    @Override
    public List<String> findAllMedia() {
        return activityAnalysisMapper.selectAllMedia();
    }

    @Override
    public void contactPointDownload(HttpServletResponse response, MediaSlotPageDTO dto) throws IOException {
        List<MediaSlot> mediaSlot = this.getMediaSlotList(dto);

        String fileName = System.currentTimeMillis() + "";

        List<ContactPointExcel> list = mediaSlot.stream()
                .map(m -> {
                    ContactPointExcel excel = new ContactPointExcel();
                    BeanUtils.copyProperties(m, excel);
                    return excel;
                }).collect(Collectors.toList());

        EasyExcel.write(response.getOutputStream(), ContactPointExcel.class)
                .registerWriteHandler(ExcelUtil.getHorizontalCellStyleStrategy(response, fileName))
                .sheet("触点归因排名")
                .doWrite(list);
    }

    @Override
    public Map<String, List<String>> findTypeAndCNames() {
        List<ActivityAnalysis> list = activityAnalysisMapper.selectByExample(null);

        Map<String, List<ActivityAnalysis>> collect = list.stream()
                .collect(Collectors.groupingBy(ActivityAnalysis::getActivityType));
        Map<String, List<String>> map = new HashMap<>();

        collect.forEach((key, value) -> {
            List<String> list1 = value.stream().map(ActivityAnalysis::getCampaignName).collect(Collectors.toList());

            map.put(key, list1);
        });
        return map;
    }

    @Override
    public ActivityAnalysisAndAlogAndDiff comparisonOfCoreIndicators(String cidA, String cidB) {
        ActivityAnalysis a = activityAnalysisMapper.selectAnByCId(cidA);
        ActivityAnalysis b = activityAnalysisMapper.selectAnByCId(cidB);

        Alog aAlog = activityAnalysisMapper.getAlog(cidA);
        Alog bAlog = activityAnalysisMapper.getAlog(cidB);

        a.setAlog(aAlog);
        b.setAlog(bAlog);

        AlogDiff diff = AlogUtil.getAlogDiff(aAlog,bAlog);
        diff.setCostDiff(a.getCost().subtract(b.getCost()));
        diff.setMonitorRateDiff(a.getMonitorRate().subtract(b.getMonitorRate()));
        diff.setExposureCountDiff(a.getExposureCount()-b.getExposureCount());
        diff.setExposureUserCountDiff(a.getExposureUserCount()-b.getExposureUserCount());
        diff.setClickCountDiff(a.getClickCount()-b.getClickCount());
        diff.setClickUserCountDiff(a.getClickUserCount()-b.getClickUserCount());
        diff.setMonthlyActiveMemberCountDiff(a.getMonthlyActiveMemberCount()-b.getMonthlyActiveMemberCount());
        diff.setMonthlyActiveMemberGmvDiff(a.getMonthlyActiveMemberGmv().subtract(b.getMonthlyActiveMemberGmv()));
        diff.setNewMemberAcquisitionCountDiff(a.getNewMemberAcquisitionCount()-b.getNewMemberAcquisitionCount());
        diff.setNewMemberAcquisitionGmvDiff(a.getNewMemberAcquisitionGmv().subtract(b.getNewMemberAcquisitionGmv()));
        diff.setPeriodicMonthlyActiveUserCountDiff(a.getPeriodicMonthlyActiveUserCount()-b.getPeriodicMonthlyActiveUserCount());
        diff.setPeriodicMonthlyActiveUserGmvDiff(a.getPeriodicMonthlyActiveUserGmv().subtract(b.getPeriodicMonthlyActiveUserGmv()));
        diff.setPeriodicNewMemberCountDiff(a.getPeriodicNewMemberCount()-b.getPeriodicNewMemberCount());
        diff.setPeriodicNewMemberGmvDiff(a.getPeriodicNewMemberGmv().subtract(b.getPeriodicNewMemberGmv()));
        diff.setNextMonthActiveMemberCountDiff(a.getNextMonthActiveMemberCount()-b.getNextMonthActiveMemberCount());
        diff.setNextMonthActiveMemberGmvDiff(a.getNextMonthActiveMemberGmv().subtract(b.getNextMonthActiveMemberGmv()));
        diff.setNextMonthNewMemberCountDiff(a.getNextMonthNewMemberCount()-b.getNextMonthNewMemberCount());
        diff.setNextMonthNewMemberGmvDiff(a.getNextMonthNewMemberGmv().subtract(b.getNextMonthNewMemberGmv()));

        ActivityAnalysisAndAlogAndDiff data = new ActivityAnalysisAndAlogAndDiff();
        data.setActivityAnalysisA(a);
        data.setActivityAnalysisB(b);
        data.setDiff(diff);
        return data;
    }

    @Override
    public void comparisonOfCoreIndicatorsDownload(String cidA, String cidB, HttpServletResponse response) throws IOException {
        ActivityAnalysisAndAlogAndDiff data = this.comparisonOfCoreIndicators(cidA, cidB);

        ActivityAnalysis a = data.getActivityAnalysisA();
        ActivityAnalysis b = data.getActivityAnalysisB();
        Alog aAlog = a.getAlog();
        Alog bAlog = b.getAlog();
        AlogDiff diff = data.getDiff();

        ActivityAnalysisAndAlogAndDiffExcel aExcel = new ActivityAnalysisAndAlogAndDiffExcel();
        BeanUtils.copyProperties(a,aExcel);
        BeanUtils.copyProperties(aAlog,aExcel);
        BeanUtils.copyProperties(diff,aExcel);

        ActivityAnalysisAndAlogAndDiffExcel bExcel = new ActivityAnalysisAndAlogAndDiffExcel();
        BeanUtils.copyProperties(b,bExcel);
        BeanUtils.copyProperties(bAlog,bExcel);
        BeanUtils.copyProperties(diff,bExcel);

        List<ActivityAnalysisAndAlogAndDiffExcel> list = new ArrayList<>();
        list.add(aExcel);
        list.add(bExcel);

        String fileName = URLEncoder.encode("多活动核心指标对比" + System.currentTimeMillis(), "UTF-8");

        EasyExcel.write(response.getOutputStream(), ActivityAnalysisAndAlogAndDiffExcel.class)
                .registerWriteHandler(ExcelUtil.getHorizontalCellStyleStrategy(response, fileName))
                .sheet("多活动分媒介分平台类型对比")
                .doWrite(list);
    }

    @Override
    public List<ActivityAnalysis> findActivityCpm() {
        return activityAnalysisMapper.selectActivityCpm();
    }
}
